home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / network / ncsasock / netdb.c < prev    next >
Text File  |  1996-07-05  |  12KB  |  511 lines

  1. /*
  2.  * BSD-style socket emulation library for the Mac
  3.  * Original author: Tom Milligan
  4.  * Current author: Charlie Reiman - creiman@ncsa.uiuc.edu
  5.  *
  6.  * This source file is placed in the public domian.
  7.  * Any resemblance to NCSA Telnet, living or dead, is purely coincidental.
  8.  *
  9.  *      National Center for Supercomputing Applications
  10.  *      152 Computing Applications Building
  11.  *      605 E. Springfield Ave.
  12.  *      Champaign, IL  61820
  13.  */
  14.  
  15. /*
  16.  *    Internet name routines that every good unix program uses...
  17.  *
  18.  *        gethostbyname
  19.  *        gethostbyaddr
  20.  *      gethostid
  21.  *        gethostname
  22.  *        getdomainname
  23.  *        inet_addr
  24.  *        inet_ntoa
  25.  *        getservbyname
  26.  *        getprotobyname
  27.  */
  28.  
  29. #ifdef USEDUMP
  30. # pragma load "Socket.dump"
  31. #else
  32. # include <Stdio.h>
  33. # include <Types.h>
  34. # include <Resources.h>
  35. # include <Errors.h>
  36. # include <OSUtils.h>
  37.  
  38. # include <s_types.h>
  39. # include <netdb.h>
  40. # include <neti_in.h>
  41. # include <s_socket.h>
  42. # include <s_time.h>
  43. # include <neterrno.h>
  44.  
  45. # include "sock_str.h"
  46. # include "sock_int.h"
  47. #endif
  48.  
  49. #include <Ctype.h>
  50. #include <a_namesr.h>
  51. #include <s_param.h>
  52. /* #include <sock_ext.h> */
  53.  
  54.  
  55. extern SocketPtr sockets;
  56. extern SpinFn spinroutine;
  57. pascal void DNRDone(struct hostInfo *hostinfoPtr,char *done);
  58.  
  59. int h_errno;
  60.  
  61. /*
  62.  *   Gethostbyname and gethostbyaddr each return a pointer to an
  63.  *   object with the following structure describing an Internet
  64.  *   host referenced by name or by address, respectively. This
  65.  *   structure contains the information obtained from the MacTCP
  66.  *   name server.
  67.  *
  68.  *   struct    hostent 
  69.  *   {
  70.  *        char *h_name;
  71.  *        char **h_aliases;
  72.  *        int  h_addrtype;
  73.  *        int  h_length;
  74.  *        char **h_addr_list;
  75.  *   };
  76.  *   #define   h_addr  h_addr_list[0]
  77.  *
  78.  *   The members of this structure are:
  79.  *
  80.  *   h_name       Official name of the host.
  81.  *
  82.  *   h_aliases    A zero terminated array of alternate names for the host.
  83.  *
  84.  *   h_addrtype   The type of address being  returned; always AF_INET.
  85.  *
  86.  *   h_length     The length, in bytes, of the address.
  87.  *
  88.  *   h_addr_list  A zero terminated array of network addresses for the host.
  89.  *
  90.  *   Error return status from gethostbyname and gethostbyaddr  is
  91.  *   indicated by return of a null pointer.  The external integer
  92.  *   h_errno may then  be checked  to  see  whether  this  is  a
  93.  *   temporary  failure  or  an  invalid  or  unknown  host.  The
  94.  *   routine herror  can  be  used  to  print  an error  message
  95.  *   describing the failure.  If its argument string is non-NULL,
  96.  *   it is printed, followed by a colon and a space.   The  error
  97.  *   message is printed with a trailing newline.
  98.  *
  99.  *   h_errno can have the following values:
  100.  *
  101.  *     HOST_NOT_FOUND  No such host is known.
  102.  *
  103.  *     TRY_AGAIN    This is usually a temporary error and
  104.  *                    means   that  the  local  server  did  not
  105.  *                    receive a response from  an  authoritative
  106.  *                    server.   A  retry at some later time may
  107.  *                    succeed.
  108.  *
  109.  *     NO_RECOVERY    Some unexpected server failure was encountered.
  110.  *                     This is a non-recoverable error.
  111.  *
  112.  *     NO_DATA        The requested name is valid but  does  not
  113.  *                    have   an IP  address;  this  is not  a
  114.  *                    temporary error. This means that the  name
  115.  *                    is known  to the name server but there is
  116.  *                    no address  associated  with  this  name.
  117.  *                    Another type of request to the name server
  118.  *                    using this domain name will result in  an
  119.  *                    answer;  for example, a mail-forwarder may
  120.  *                    be registered for this domain.
  121.  *                    (NOT GENERATED BY THIS IMPLEMENTATION)
  122.  */
  123.  
  124. static struct hostInfo macHost;
  125.  
  126. #define MAXALIASES 0
  127. static char *aliasPtrs[MAXALIASES+1] = {NULL};
  128. static ip_addr *addrPtrs[NUM_ALT_ADDRS+1];
  129.  
  130. static struct hostent  unixHost = 
  131. {
  132.     macHost.cname,
  133.     aliasPtrs,
  134.     AF_INET,
  135.     sizeof(ip_addr),
  136.     (char **) addrPtrs
  137. };
  138.  
  139.  
  140.  
  141. struct hostent * gethostbyname(char *name)
  142. {
  143.     Boolean done;
  144.     int i;
  145.     ResultUPP dnrdoneUPP;
  146.     
  147.     dnrdoneUPP = NewResultProc(DNRDone); 
  148.     
  149.  
  150. #if    NETDB_DEBUG >= 3
  151.     dprintf("gethostbyname: '%s'\n",name);
  152. #endif
  153.  
  154.     sock_init();
  155.  
  156.     for (i=0; i<NUM_ALT_ADDRS; i++)
  157.         macHost.addr[i] = 0;
  158.     done = false;
  159.     if (StrToAddr(name,&macHost, dnrdoneUPP, (char *) &done) == cacheFault)
  160.     {
  161. #if NETDB_DEBUG >= 5
  162.         dprintf("gethostbyname: spinning\n");
  163. #endif
  164.         SPINP(!done,SP_NAME,0L)
  165.  
  166. #if NETDB_DEBUG >= 5
  167.         dprintf("gethostbyname: done spinning\n");
  168. #endif
  169.     }
  170.     switch (macHost.rtnCode)
  171.     {
  172.         case noErr: break;
  173.         
  174.         case nameSyntaxErr:    h_errno = HOST_NOT_FOUND;    return(NULL);
  175.         case cacheFault:    h_errno = NO_RECOVERY;        return(NULL);
  176.         case noResultProc:    h_errno = NO_RECOVERY;        return(NULL);
  177.         case noNameServer:    h_errno = HOST_NOT_FOUND;    return(NULL);
  178.         case authNameErr:    h_errno = HOST_NOT_FOUND;    return(NULL);
  179.         case noAnsErr:        h_errno = TRY_AGAIN;        return(NULL);
  180.         case dnrErr:        h_errno = NO_RECOVERY;        return(NULL);
  181.         case outOfMemory:    h_errno = TRY_AGAIN;        return(NULL);
  182.         case notOpenErr:    h_errno = NO_RECOVERY;        return(NULL);
  183.         default:            h_errno = NO_RECOVERY;        return(NULL);
  184.     }
  185.     
  186. #if NETDB_DEBUG >= 5
  187.     dprintf("gethostbyname: name '%s' addrs %08x %08x %08x %08x\n",
  188.             macHost.cname,
  189.             macHost.addr[0],macHost.addr[1],
  190.             macHost.addr[2],macHost.addr[3]);
  191. #endif
  192.  
  193.     /* was the 'name' an IP address? */
  194.     if (macHost.cname[0] == 0)
  195.     {
  196.         h_errno = HOST_NOT_FOUND;
  197.         return(NULL);
  198.     }
  199.     
  200.     /* for some reason there is a dot at the end of the name */
  201.     i = strlen(macHost.cname) - 1;
  202.     if (macHost.cname[i] == '.')
  203.         macHost.cname[i] = 0;
  204.     
  205.     for (i=0; i<NUM_ALT_ADDRS && macHost.addr[i]!=0; i++)
  206.     {
  207.         addrPtrs[i] = &macHost.addr[i];
  208.     }
  209.     addrPtrs[i] = NULL;
  210.     
  211.     return(&unixHost);
  212. }
  213.  
  214. struct hostent * gethostbyaddr(long *addrP,Int4 len,Int4 type)
  215. {
  216. #pragma unused(len)
  217. #pragma unused(type)
  218.     Boolean done;
  219.     int i;
  220.     ResultUPP dnrdoneUPP;
  221.     
  222.     dnrdoneUPP = NewResultProc(DNRDone); 
  223.     
  224. #if    NETDB_DEBUG >= 3
  225.     dprintf("gethostbyaddr: %08x\n",*addrP);
  226. #endif
  227.  
  228.     sock_init();
  229.     
  230.     for (i=0; i<NUM_ALT_ADDRS; i++)
  231.         macHost.addr[i] = 0;
  232.     done = false;
  233.     if (AddrToName(*addrP,&macHost,dnrdoneUPP, (char *) &done) == cacheFault)
  234.     {
  235. #if NETDB_DEBUG >= 5
  236.         dprintf("gethostbyaddr: spinning\n");
  237. #endif
  238.  
  239.         SPINP(!done,SP_ADDR,0L)
  240. #if NETDB_DEBUG >= 5
  241.         dprintf("gethostbyaddr: done spinning\n");
  242. #endif
  243.     }
  244.     switch (macHost.rtnCode)
  245.     {
  246.         case noErr: break;
  247.         
  248.         case cacheFault:    h_errno = NO_RECOVERY;        return(NULL);
  249.         case noNameServer:    h_errno = HOST_NOT_FOUND;    return(NULL);
  250.         case authNameErr:    h_errno = HOST_NOT_FOUND;    return(NULL);
  251.         case noAnsErr:        h_errno = TRY_AGAIN;        return(NULL);
  252.         case dnrErr:        h_errno = NO_RECOVERY;        return(NULL);
  253.         case outOfMemory:    h_errno = TRY_AGAIN;        return(NULL);
  254.         case notOpenErr:    h_errno = NO_RECOVERY;        return(NULL);
  255.         default:            h_errno = NO_RECOVERY;        return(NULL);
  256.     }
  257. #if NETDB_DEBUG >= 5
  258.     dprintf("gethostbyaddr: name '%s' addrs %08x %08x %08x %08x\n",
  259.             macHost.cname,
  260.             macHost.addr[0],macHost.addr[1],
  261.             macHost.addr[2],macHost.addr[3]);
  262. #endif
  263.     /* for some reason there is a dot at the end of the name */
  264.     i = strlen(macHost.cname) - 1;
  265.     if (macHost.cname[i] == '.')
  266.         macHost.cname[i] = 0;
  267.     
  268.     for (i=0; i<NUM_ALT_ADDRS; i++)
  269.     {
  270.         addrPtrs[i] = &macHost.addr[i];
  271.     }
  272.     addrPtrs[NUM_ALT_ADDRS] = NULL;
  273.     
  274.     return(&unixHost);
  275. }
  276.  
  277. char *
  278. inet_ntoa(ip_addr inaddr)
  279. {
  280.     sock_init();
  281.     
  282.     (void) AddrToStr(inaddr,macHost.cname);
  283.     return(macHost.cname);
  284. }
  285.  
  286. /*ip_addr inet_addr(char *address)*/
  287. extern unsigned long inet_addr(const char *address) 
  288. {
  289. #ifndef JAE
  290. OSErr retval;
  291. #endif
  292.     sock_init();
  293. #ifndef JAE
  294.     if ((retval = StrToAddr((char*)address,&macHost,NULL,NULL)) != noErr)
  295. #else
  296.  
  297.  
  298.     if (StrToAddr(address,&macHost,NULL,NULL) != noErr)
  299. #endif
  300.         return((ip_addr)-1);
  301.     
  302. #if NETDB_DEBUG >= 5
  303.     dprintf("inet_addr: name '%s' addr %08x\n",
  304.             macHost.cname,macHost.addr[0]);
  305. #endif
  306.  
  307.     /* was the 'address' really a name? */
  308.     if (macHost.cname[0] != 0)
  309.         return((ip_addr)-1);
  310.     
  311.     return(macHost.addr[0]);
  312. }
  313.  
  314. /*
  315.  * gethostid()
  316.  *
  317.  * Get Internet address. If the application can get by with just
  318.  * this, it avoids the muss and fuss of DNR.
  319.  */
  320.  
  321. unsigned long gethostid()
  322. {
  323.     ip_addr ipaddr;
  324.     
  325.     ipaddr = xIPAddr();
  326.     
  327.     return ((unsigned long) ipaddr);
  328. }
  329.  
  330. /*
  331.  * gethostname()
  332.  *
  333.  * Try to get my host name from DNR. If it fails, just return my
  334.  * IP address as ASCII. This is non-standard, but it's a mac,
  335.  * what do you want me to do?
  336.  */
  337.  
  338. int gethostname(char * machname, long buflen)
  339. {
  340.     ip_addr ipaddr;
  341.     struct    hostent *hp;
  342.     
  343. #if    NETDB_DEBUG >= 3
  344.     dprintf("gethostname: \n");
  345. #endif
  346.  
  347.     sock_init();        /* initialize the socket stuff. */
  348.     ipaddr = xIPAddr();
  349.     hp = gethostbyaddr( (long*)&ipaddr, sizeof(ip_addr), AF_INET);
  350.     if( hp == NULL) 
  351.         sprintf (machname, "%d.%d.%d.%d",ipaddr>>24,
  352.                                 ipaddr>>16 & 0xff,
  353.                                 ipaddr>>8 & 0xff,
  354.                                 ipaddr & 0xff);
  355.     else
  356.         strncpy( machname, hp->h_name, buflen);
  357.     
  358.     machname[buflen-1] = 0;  /* extra safeguard */
  359.     return(0);
  360. }
  361.  
  362.  
  363. /*
  364.  *    getservbybname()
  365.  *
  366.  *    Real kludgy.  Should at least consult a resource file as the service
  367.  *    database.
  368.  */
  369. typedef struct services {
  370.     char        sv_name[12];
  371.     short        sv_number;
  372.     char        sv_protocol[5];
  373. } services_t, *services_p;
  374.  
  375. static    struct services    slist[] = 
  376.     {"echo", 7, "udp"},
  377.     {"discard", 9, "udp"},
  378.     {"time", 37, "udp"},
  379.     {"domain", 53, "udp"},
  380.     {"sunrpc", 111, "udp"},
  381.     {"tftp", 69, "udp"},
  382.     {"biff", 512, "udp"},
  383.     {"who", 513, "udp"},
  384.     {"talk", 517, "udp"},
  385.     {"route", 520, "udp"},
  386.     {"new-rwho", 550, "udp"},
  387.     {"netstat", 15, "tcp"},
  388.     {"ftp-data", 20, "tcp"},
  389.     {"ftp", 21, "tcp"},
  390.     {"telnet", 23, "tcp"},
  391.     {"smtp", 25, "tcp"},
  392.     {"time", 37, "tcp"},
  393.     {"whois", 43, "tcp"},
  394.     {"domain", 53, "tcp"},
  395.     {"hostnames", 101, "tcp"},
  396.     {"nntp", 119, "tcp"},
  397.     {"finger", 79, "tcp"},
  398.     {"uucp-path", 117, "tcp"},
  399.     {"untp", 119, "tcp"},
  400.     {"ntp", 123, "tcp"},
  401.     {"exec", 512, "tcp"},
  402.     {"login", 513, "tcp"},
  403.     {"shell", 514, "tcp"},
  404.     {"printer", 515, "tcp"},
  405.     {"courier", 530, "tcp"},
  406.     {"uucp", 540, "tcp"},
  407.     {"", 0, "" }
  408. };
  409.                      
  410. #define    MAX_SERVENT            10
  411. static     struct servent        servents[MAX_SERVENT];
  412. static     int                    servent_count=0;
  413.  
  414. struct servent * getservbyname (char    *name,char    * proto)
  415. {
  416.     int                i;
  417.     struct    servent    *se;
  418.     
  419.     if (strcmp (proto, "udp") == 0 || strcmp (proto, "tcp") == 0) 
  420.     {
  421.         for (i=0; slist[i].sv_number != 0; i++)
  422.             if (strcmp (slist[i].sv_name, name) == 0)
  423.                 if (strcmp (slist[i].sv_protocol, proto) == 0) 
  424.                 {
  425.                     se = &servents[servent_count];
  426.                     se->s_name = slist[i].sv_name;
  427.                     se->s_aliases = NULL;
  428.                     se->s_port = slist[i].sv_number;
  429.                     se->s_proto = slist[i].sv_protocol;
  430.                     servent_count = (servent_count +1) % MAX_SERVENT;
  431.                     return (se);
  432.                 }
  433.         return (NULL);
  434.     }
  435.     else 
  436.     {
  437.         errno = errno_long = EPROTONOSUPPORT;
  438.         return(NULL);
  439.     }
  440. }
  441.  
  442. static    char    tcp[] = "tcp";
  443. static    char    udp[] = "udp";
  444. #define    MAX_PROTOENT            10
  445. static     struct protoent        protoents[MAX_PROTOENT];
  446. static     int                    protoent_count=0;
  447.  
  448. struct protoent * getprotobyname (char* name)
  449. {
  450.     struct protoent *pe;
  451.     
  452.     pe = &protoents[protoent_count];
  453.     if (strcmp (name, "udp") == 0) 
  454.     {
  455.         pe->p_name = udp;
  456.         pe->p_proto = IPPROTO_UDP;
  457.     }
  458.     else if (strcmp (name, "tcp") == 0) 
  459.     {
  460.         pe->p_name = tcp;
  461.         pe->p_proto = IPPROTO_TCP;
  462.     }
  463.     else 
  464.     {    
  465.         errno = errno_long = EPROTONOSUPPORT;
  466.         return(NULL);
  467.     }
  468.     pe->p_aliases = NULL;
  469.     protoent_count = (protoent_count +1) % MAX_PROTOENT;
  470.     return (pe);
  471. }
  472.  
  473. char *h_errlist[] = 
  474. {
  475.     "Error 0",
  476.     "Unknown host",                        /* 1 HOST_NOT_FOUND */
  477.     "Host name lookup failure",            /* 2 TRY_AGAIN */
  478.     "Unknown server error",                /* 3 NO_RECOVERY */
  479.     "No address associated with name",    /* 4 NO_ADDRESS */
  480. };
  481.  
  482. const int    h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
  483.  
  484. void herror(char *s)
  485.     {
  486.     fprintf(stderr,"%s: ",s);
  487.     if (h_errno < h_nerr)
  488.         fprintf(stderr,h_errlist[h_errno]);
  489.     else
  490.         fprintf(stderr,"error %d",h_errno);
  491.     fprintf(stderr,"\n");
  492.     }
  493.  
  494. char *herror_str(int theErr) {
  495.     if (theErr > h_nerr )
  496.         return NULL;
  497.     else
  498.         return h_errlist[theErr];
  499.         }
  500.  
  501. #ifndef COMP_CODEWAR
  502. #pragma segment SOCK_RESIDENT
  503. #endif
  504.  
  505. pascal void DNRDone(struct hostInfo *hostinfoPtr,char *done)
  506. {
  507. #pragma unused(hostinfoPtr)
  508.     *done = true;
  509. }
  510.